package com.piketao.search;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.item.piketao.dao.*;
import com.piketao.client.BrandClient;
import com.piketao.client.CategoryClient;
import com.piketao.client.GoodsClient;
import com.piketao.client.SpecificationClient;
import com.piketao.common.pojo.PageInfo;
import com.piketao.dao.Goods;
import com.piketao.repository.GoodsRepository;
import com.piketao.vo.SearchRequest;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.elasticsearch.index.query.Operator;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.query.FetchSourceFilter;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author: xinglongge
 * @Date: 2020/3/9 18 07
 * @Description:
 */
@Service
public class SearchService {

    private final CategoryClient categoryClient;
    private final BrandClient brandClient;
    private final GoodsClient goodsClient;
    private final SpecificationClient specificationClient;
    private final ObjectMapper objectMapper;
    private final GoodsRepository goodsRepository;

    @Autowired
    public SearchService(CategoryClient categoryClient, BrandClient brandClient,
                         GoodsClient goodsClient, SpecificationClient specificationClient,
                         GoodsRepository goodsRepository) {
        this.categoryClient = categoryClient;
        this.brandClient = brandClient;
        this.goodsClient = goodsClient;
        this.specificationClient = specificationClient;
        this.objectMapper = new ObjectMapper();
        this.goodsRepository=goodsRepository;
    }

    @Transactional(rollbackFor = Exception.class)
    public Goods buildGoods(Spu spu) throws IOException {
        Goods goods = new Goods();

        goods.setId(spu.getId());
        goods.setCid1(spu.getCid1());
        goods.setCid2(spu.getCid2());
        goods.setCid3(spu.getCid3());
        goods.setBrandId(spu.getBrandId());
        goods.setCreateTime(spu.getCreateTime());
        goods.setSubTitle(spu.getSubTitle());
        //需要分类名称 品牌名称
        List<String> names = categoryClient.queryNamesByIds(Arrays.asList(spu.getCid1(), spu.getCid2(), spu.getCid3()));
        Brand brand = brandClient.queryBrandById(spu.getBrandId());
        goods.setAll(spu.getTitle() + " " + StringUtils.join(names, " ") + " " + brand.getName());
        //获取spu下的所有sku的价格
        List<Sku> skus = goodsClient.querySkuBySpuId(spu.getId());
        List<Long> prices = skus.stream().map(Sku::getPrice).collect(Collectors.toList());
        goods.setPrice(prices);
        //获取spu下的所有sku，并转化为json字符串
        List<Map<String, Object>> skuMapList = new ArrayList<>();
        skus.forEach(sku -> {
            HashMap<String, Object> map = new HashMap<>(4);
            map.put("id", sku.getId());
            map.put("title", sku.getTitle());
            map.put("price", sku.getPrice());
            map.put("image", StringUtils.isBlank(sku.getImages()) ? "" : StringUtils.split(sku.getImages(), ",")[0]);
            skuMapList.add(map);
        });
        goods.setSkus(objectMapper.writeValueAsString(skuMapList));
        //获取所有的查询规格参数 name:value
        List<SpecParam> specParams = specificationClient.queryParams(null, spu.getCid3(), null, true);
        //先根据spuId拿到spuDetail
        SpuDetail spuDetail = goodsClient.querySpuDetailById(spu.getId());
        Map<String, Object> genericMap = objectMapper.readValue(spuDetail.getGenericSpec(), new TypeReference<Map<String, Object>>() {
        });
        Map<String, List<Object>> specialMap = objectMapper.readValue(spuDetail.getSpecialSpec(), new TypeReference<Map<String, List<Object>>>() {
        });

        Map<String, Object> specMap = specParams.stream().collect(Collectors.toMap(
                SpecParam::getName, specParam -> {
                    if (specParam.getGeneric()) {
                        String value = genericMap.get(specParam.getId().toString()).toString();
                        if (specParam.getNumeric()) {

                            value = chooseSegment(value, specParam);
                            return value;
                        }
                        return value;
                    } else {
                        return specialMap.get(specParam.getId().toString());
                    }
                }
        ));
        goods.setSpecs(specMap);


        return goods;
    }

    private String chooseSegment(String value, SpecParam p) {
        double val = NumberUtils.toDouble(value);
        String result = "其它";
        // 保存数值段
        for (String segment : p.getSegments().split(",")) {
            String[] segs = segment.split("-");
            // 获取数值范围
            double begin = NumberUtils.toDouble(segs[0]);
            double end = Double.MAX_VALUE;
            if (segs.length == 2) {
                end = NumberUtils.toDouble(segs[1]);
            }
            // 判断是否在范围内
            if (val >= begin && val < end) {
                if (segs.length == 1) {
                    result = segs[0] + p.getUnit() + "以上";
                } else if (begin == 0) {
                    result = segs[1] + p.getUnit() + "以下";
                } else {
                    result = segment + p.getUnit();
                }
                break;
            }
        }
        return result;
    }

    public PageInfo<Goods> search(SearchRequest search) {
        String key = search.getKey();
        if (StringUtils.isBlank(key)) {
            return null;
        }

        //自定义查询构建器
        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
        //添加分页，页码从0开始
        queryBuilder.withPageable(PageRequest.of(search.getPage() - 1, search.getSize()));
        //添加查询条件
        queryBuilder.withQuery(QueryBuilders.matchQuery("all", key).operator(Operator.AND));
        //添加结果集过滤
        queryBuilder.withSourceFilter(new FetchSourceFilter(new String[]{"id","skus","subTitle"},null));
        //执行查询，获取结果集
        Page<Goods> goodsPage = goodsRepository.search(queryBuilder.build());

        return new PageInfo<>(goodsPage.getTotalElements(),goodsPage.getTotalPages(),goodsPage.getContent());
    }

}
